前端必备技能:json-server全攻略

原创 张培跃 [张培跃](javascript:void(0)😉 2020-08-23

在项目的初始阶段,后端提供的接口或数据可能是不完整的,作为一名前端开发工程师,不可避免的要使用mock的数据。如果此时的你不想使用简单的静态数据,而是想自己在本地启动一个server来模拟请求相关的操作,那么json-server是一个不错的选择。

json-serve可以帮助我们快速搭建一个mock-server本地服务,可以根据不同的后缀获取到不同的数据。

一、准备工作

1、安装Node

由于json-server需要通过Node对其进行启动,所以首先要安装Node。Node可自行安装,在此不再进行演示。

2、全局安装json-server

版本不能安装太高, 否则有跟nodejs版本不兼容的风险

npm install json-server@0.16.3 --location=global
pnpm add json-server@0.16.3 -g

3、查看版本

在cmd控制台中输入以下命令,查看版本号。用于验证是否安装成功。

json-server -v

4、准备一份JSON文件

我这里准备的是一份名字为score.json的文件,用于存放虚拟数据。

{  "scoreList":[    {"id":1,"userName":"张三","age":12,"sex":"男","score":{"yuWen":10,"shuXue":20,"yingYu":30}},    {"id":2,"userName":"李四","age":21,"sex":"女","score":{"yuWen":12,"shuXue":45,"yingYu":37}},    {"id":3,"userName":"王五","age":56,"sex":"男","score":{"yuWen":12,"shuXue":20,"yingYu":30}},    {"id":4,"userName":"赵六","age":23,"sex":"女","score":{"yuWen":19,"shuXue":21,"yingYu":65}},    {"id":5,"userName":"严七","age":12,"sex":"男","score":{"yuWen":34,"shuXue":67,"yingYu":43}},    {"id":6,"userName":"沈八","age":43,"sex":"女","score":{"yuWen":56,"shuXue":76,"yingYu":30}},    {"id":7,"userName":"钱九","age":13,"sex":"男","score":{"yuWen":24,"shuXue":89,"yingYu":30}},    {"id":8,"userName":"张十","age":12,"sex":"女","score":{"yuWen":10,"shuXue":54,"yingYu":31}}  ]}

二、启动服务

1、常用命令选项:

•-- watch:通过该命令可以实时监测score.json的变化,如果省略该命令,即使score.json发生变化,刷新、或重新发送请求,仍然会返回初次启动服务时的数据。简写形式为:-w•--port:指定服务的端口号,可省略,默认为3000。简写形式:-p•--host:设置域,可省略。简写形式:-H

json-server --watch score.json --port 8090  --host 127.0.0.1

上方命令可简写为:

json-server score.json -w -p 8090 -H 127.0.0.1

但,一般通过下面命令,即可完基本工作:

json-server -w score.json

2、工作场景建议

如果你已知项目接口域名及端口号,为避免后续更改接口信息。我们可以这样做:

•假设项目接口域名为:api.zhangpeiyue.com,端口号为:80•设置host映射:用记事本打开C:\Windows\System32\drivers\etc目录中的hosts文件。底部增加:127.0.0.1 api.zhangpeiyue.com,该文件如果不允许修改,增加相对应的权限即可。•启动服务命令:

json-server --watch score.json --port 80  --host api.zhangpeiyue.com

由于80是默认端口号,所以我们可以通过api.zhangpeiyue.com来对数据进行操作了。

3、通过package.json文件启动项目

启动json-server时, 如果自定义配置的参数过多,容易出现命令敲错的现象。我们可以在创建一个名字为package.json的文件,内容为:

{
    "scripts": {
        "score": "json-server --watch score.json --port 80  --host api.zhangpeiyue.com"
    }
}

通过npm run score启动即可。

4、自定义配置文件

json-server允许我们把所有的配置放到一个配置文件中,这个配置文件默认json-server.json。配置文件的主要内容如下:

{  
	"port": 80,  // 自定义服务监听端口  
	"watch": true, // 服务监听  
	"host": "api.zhangpeiyue.com",// 指定域  
	"static": "./public", // 静态文件目录,可以将项目的HTML,JS,IMG等资源放在这里  
	"read-only": false,  // 是否只允许get请求  
	"no-cors":false, // 是否允许跨域访问  
	"no-gzip": false, // 是否可压缩  
	"routes": "route.json" // 自定义路由,这个配置可以暂时省略,后续会有所涉及
}

可以通过json-server --watch score.json启动项目。

5、输出类似以下内容,说明启动成功。

图片

6、其它相关启动参数

图片

三、获取数据(get)

1、get获取scoreList属性

http://api.zhangpeiyue.com/scoreList

(async () => {
    const { data } = await axios.get("http://api.zhangpeiyue.com/scoreList"); 	
    console.log(data);
})();

2、两种获取数据方式

通过以下两种方式可get获取scoreList属性当中id为1的数据:

http://api.zhangpeiyue.com/scoreList/1

(async ()=>{    
	const {data} = await axios.get("http://api.zhangpeiyue.com/scoreList/1"); 
    console.log(data);
})();

http://api.zhangpeiyue.com/scoreList?id=1

(async ()=>{    
	const {data} = await axios.get("http://api.zhangpeiyue.com/scoreList",{params:{id:1}});    
	console.log(data);
})();

3、单条件查找

查找scoreList属性author李四的数据

http://api.zhangpeiyue.com/scoreList?userName=李四

(async () => {
    const { data } = await axios.get("http://api.zhangpeiyue.com/scoreList", {
        params: {
            userName: "李四"
        }
    });
    console.log(data);
})();

4、多条件查找

查找scoreList属性sexage12的数据

http://api.zhangpeiyue.com/scoreList?sex=男&age=12

(async () => {
    const { data } = await axios.get("http://api.zhangpeiyue.com/scoreList", {
        params: {
            sex: "男",
            age: 12
        }
    });
    console.log(data);
})();

5、q全局搜索(模糊查询)

查询scoreList所有属性值中包含的数据

http://api.zhangpeiyue.com/scoreList?q=张

(async () => {
    const { data } = await axios.get("http://api.zhangpeiyue.com/scoreList", {
        params: {
            q: "张"
        }
    });
    console.log(data);
})();

6、深层属性查找

可以用.访问更深层的属性:查询scoreList属性score的属性yuWen12的数据:

http://api.zhangpeiyue.com/scoreList?roles.yuWen=12

(async () => {
    const { data } = await axios.get("http://api.zhangpeiyue.com/scoreList", {
        params: {
            ["score.yuWen"]: 12
        }
    });
    console.log(data);
})();

7、分页查找 _page and _limit

通过_page and _limit 实现对数据的分页:将scoreList每页显示3条记录,查询第2页内容:

http://api.zhangpeiyue.com/scoreList?_page=2&_limit=3

(async () => {
    const { data } = await axios.get(" http://api.zhangpeiyue.com/scoreList", {
        params: {
            _page: 2,
            _limit: 3
        }
    });
    console.log(data);
})();

8、排序 _sort_order

通过_sort_order 对数据进行排序。_sort指定排序的属性,_order指定排序的类型(asc为升序,desc为降序)

•按age的倒序排列: http://api.zhangpeiyue.com/scoreList?_sort=age&_order=desc

(async () => {
    const { data } = await axios.get("http://api.zhangpeiyue.com/scoreList", {
        params: {
            _sort: "age",
            _order: "desc"
        }
    });
    console.log(data);
})();

•多条件排序:年龄相同按语文的升序排列: http://api.zhangpeiyue.com/scoreList?_sort=age,score.yuWen&_order=desc,asc

(async () => {
    const { data } = await axios.get("http://api.zhangpeiyue.com/scoreList", {
        params: {
            _sort: "age,score.yuWen",
            _order: "desc,asc"
        }
    });
    console.log(data);
})();

9、通过_start_end_limit对数据进行截取。

•截取前5条记录: http://api.zhangpeiyue.com/scoreList?_limit=5

(async () => {
    const { data } = await axios.get("http://api.zhangpeiyue.com/scoreList", {
        params: {
            _limit: 5
        }
    });
    console.log(data);
})();

•截取第3到第6的记录(共三条): http://api.zhangpeiyue.com/scoreList?_start=3&_end=6

(async () => {
    const { data } = await axios.get("http://api.zhangpeiyue.com/scoreList", {
        params: {
            _start: 3,
            _end: 6
        }
    });
    console.log(data);
})();

•从第2条记录开始截取5条记录(共5条): http://api.zhangpeiyue.com/scoreList?_start=2&_limit=5

(async () => {
    const { data } = await axios.get("http://api.zhangpeiyue.com/scoreList", {
        params: {
            _start: 2,
            _limit: 5
        }
    });
    console.log(data);
})();

10、通过操作符_gte(大于等于), _lte(小于等于), _ne(不等于), _like(模糊查询)获得数据。

•年龄大于等于23: http://api.zhangpeiyue.com/scoreList?age_gte=23

(async () => {
    const { data } = await axios.get("http://api.zhangpeiyue.com/scoreList", {
        params: {
            age_gte: 23
        }
    });
    console.log(data);
})();

四、添加数据(post)

*`http://api.zhangpeiyue.com/scoreList?age_gte=23`
(async () => {
    const { data } = await axios.post("http://api.zhangpeiyue.com/scoreList", {
        "id": 11,
        "userName": "萧十一郎",
        "age": 28,
        "sex": "男",
        "score": {
            "yuWen": 100,
            "shuXue": 100,
            "yingYu": 100
        }
    });
    console.log(data);
})();

五、删除数据(delete)

•删除id为11的数据: http://api.zhangpeiyue.com/scoreList/11

(async () => {
    const { data } = await axios.delete("http://api.zhangpeiyue.com/scoreList/11");
    console.log(data);
})();

六、更新数据(patch、put)

•通过patch请求,将id8的记录属性userName修改为张八。(patch为局部修改) http://api.zhangpeiyue.com/scoreList/8

(async () => {
    const { data } = await axios.patch("http://api.zhangpeiyue.com/scoreList/8", {
        userName: "张八"
    });
    console.log(data);
})();

•通过put请求将id8的记录替换成一个新的对象,该对象只有userName属性,值为新来的。(put为替换,id不会替换) http://api.zhangpeiyue.com/scoreList/8

(async () => {
    const { data } = await axios.put("http://api.zhangpeiyue.com/scoreList/8", {
        userName: "新来的"
    });
    console.log(data);
})();

七、自定义路由

创建route.json文件,可对路由进行如下配置:

{
    /data/data1  ==>  /data1
    "/data/*": "/$1",
    /data1/001/show ==> /data1/001
    "/:resource/:id/show": "/:resource/:id",
    /data1/Sherry ==> /data1?name=Sherry
    "/data1/:name": "/data1?name=:name",
    /data1?id=002 ==> /data/002 
    "/:anyArray\\?id=:id": "/:anyArray/:id"
}

启动:

json-server --watch score.json --routes route.json

八、json-server定制

json-server是依赖express开发而来,如有需要可进行深度定制

1、安装json-server

npm install json-server -D

2、创建server.js文件:

const jsonServer = require('json-server');//在node里面使用json-server包
const db = require('./db.js');//引入mockjs配置模块
const path = require('path');
const Mock = require('mockjs');
let mock='/mock';//定义路由根别名

//创建服务器
const server = jsonServer.create();//创建jsonserver 服务对象


//配置jsonserver服务器 中间件
server.use(jsonServer.defaults({
  static:path.join(__dirname, '/public'),//静态资源托管
}));
server.use(jsonServer.bodyParser);//抓取body数据使用json-server中间件


//响应
server.use((request, res, next) => {//可选 统一修改请求方式
  // console.log(1)
  // request.method = 'GET';
  next();
});

//登录注册校验
let mr = Mock.Random;//提取mock的随机对象
server.get(mock+'/login', (req, res) => {
  // console.log(req.query, req.body);//抓取提交过来的query和body
  let username=req.query.username;
  let password=req.query.password;
  (username === 'aa' && password === 'aa123')?
    res.jsonp({
      "err": 0,
      "msg": "登录成功",
      "data": {
        "follow": mr.integer(1,5),
        "fans": mr.integer(1,5),
        "nikename": mr.cname(),
        "icon": mr.image('20x20',mr.color(),mr.cword(1)),
        "time": mr.integer(13,13)
      }
    }) :
    res.jsonp({
      "err": 1,
      "msg": "登录失败",
    })

});
server.post(mock+'/reg', (req, res) => {
  let username=req.body.username;
  (username !== 'aa') ?
    res.jsonp({
      "err": 0,
      "msg": "注册成功",
      "data": {
        "follow": mr.integer(0,0),
        "fans": mr.integer(0,0),
        "nikename": mr.cname(),
        "icon": mr.image('20x20',mr.color(),mr.cword(1)),
        "time": mr.integer(13,13)
      }
    }) :
    res.jsonp({
      "err": 1,
      "msg": "注册失败",
    })

});

//响应mock接口 自定义返回结构 定义mock接口别名
const router = jsonServer.router(db);//创建路由对象 db为mock接口路由配置  db==object

router.render = (req, res) => {//自定义返回结构
  let len = Object.keys(res.locals.data).length; //判断数据是不是空数组和空对象
  // console.log(len);

  setTimeout(()=>{//模拟服务器延时
    res.jsonp({
      err: len !== 0 ? 0 : 1,
      msg: len !== 0 ? '成功' : '失败',
      data: res.locals.data
    })
  },1000)

  // res.jsonp(res.locals.data)

};

server.use(jsonServer.rewriter({//路由自定义别名
  [mock+"/*"]: "/$1",

    "/product\\?dataName=:dataName": "/:dataName",
    "/banner\\?dataName=:dataName": "/:dataName",
    "/detail\\?dataName=:dataName&id=:id": "/:dataName/:id",

    "/product/del\\?dataName=:dataName&id=:id": "/:dataName/:id",
    "/product/add\\?dataName=:dataName": "/:dataName",
    "/product/check\\?dataName=:dataName&id=:id": "/:dataName/:id"
}));

server.use(router);//路由响应



//开启jsonserver服务
server.listen(3333, () => {
  console.log('mock server is running')
}); 

转自: https://mp.weixin.qq.com/s/XcU-IThicHGsNSwMF3o72Ahttps://blog.csdn.net/lxw0518/article/details/105209449